/*
 * Copyright (c) 2006-2021, Ulandlink Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author         Notes
 * 2022-11-09       zkw        first version
 */

#include "app_ocpp_file_storage.h"
#include "app_application_param.h"

#define LOG_TAG "ocpp.file"
#define LOG_LVL LOG_LVL_INFO
#include "ulog.h"

bool ocpp_file_storage_init(const char *__restrict file_name) {
    int index = 0;
    FILE *fp = fopen(file_name, "r+");

    if (fp == NULL) {
        fp = fopen(file_name, "w+");
        if (!fp) {
            LOG_E("open %s failed, line:%d", file_name, __LINE__);
            return false;
        }
        if (fwrite(&index, sizeof(index), 1, fp) != 1) {
            LOG_E("write %s failed, line:%d", file_name, __LINE__);
        }
    } else {
        fseek(fp, 0, SEEK_END);
        if (ftell(fp) < 4) {
            fseek(fp, 0, SEEK_SET);
            if (fwrite(&index, sizeof(index), 1, fp) != sizeof(index)) {
                LOG_E("write %s failed, line:%d", file_name, __LINE__);
            }
        }
        fseek(fp, 0, SEEK_SET);
        fread(&index, 1, sizeof(index), fp);
        if (index > FILE_STORAGE_MAX || index < 0) {
            fclose(fp);
            fp = fopen(file_name, "w+");
            fwrite(&index, 1, sizeof(index), fp);
        }
    }

    if (fp) {
        fclose(fp);
    }
    return true;
}

bool ocpp_file_storage_write(FILE *fp, void *data, uint32_t size) {
    int index = 0;

    if (!fp) {
        LOG_E("open failed, line:%d", __LINE__);
        return false;
    }

    fseek(fp, 0, SEEK_SET);
    fread(&index, sizeof(index), 1, fp);
    fseek(fp, index * size + sizeof(index), SEEK_SET);
    if (fwrite(data, size, 1, fp) != 1) {
        LOG_E("write  failed, size:%d, line:%d", size, __LINE__);
        return false;
    }

    fseek(fp, 0, SEEK_SET);
    index++;
    if (index > FILE_STORAGE_MAX - 1) {
        index = 0;
    }
    if (fwrite(&index, sizeof(index), 1, fp) != 1) {
        LOG_E("write  failed, size:%d, line:%d", size, __LINE__);
        return false;
    }
    return true;
}

bool ocpp_key_modify(FILE *fp, void *data, uint32_t position, uint16_t data_size) {
    if (!fp) {
        LOG_E("open failed, line:%d", __LINE__);
        return false;
    }
    fseek(fp, ((position)*data_size), SEEK_SET);
    if (fwrite(data, data_size, 1, fp) != 1) {
        LOG_E("write  failed, size:%d, line:%d", data_size, __LINE__);
        return false;
    }

    return true;
}

bool customization_ocpp_file_storage_init(const char *__restrict file_name) {
    int write_index = 0;
    int read_index = 0;
    int out_flag = 0;

    log_i("bool tpye sizeof = %d",sizeof(out_flag));
    FILE *fp = fopen(file_name, "r+");
    /*创建文件，并给write指针,read指针,out指针赋初值*/
    if (fp == NULL) {
        fp = fopen(file_name, "w+");
        if (!fp) {
            LOG_E("open %s failed, line:%d", file_name, __LINE__);
            fclose(fp);
            return false;
        }
        if (fwrite(&write_index, sizeof(write_index), 1, fp) != 1) {
            LOG_E("write %s failed, line:%d", file_name, __LINE__);
        }
        if (fwrite(&read_index, sizeof(read_index), 1, fp) != 1) {
            LOG_E("write %s failed, line:%d", file_name, __LINE__);
        }
        if (fwrite(&out_flag, sizeof(out_flag), 1, fp) != 1) {
            LOG_E("write %s failed, line:%d", file_name, __LINE__);
        }    
        fclose(fp);
        return true;               
    } else {   
        fseek(fp, 0, SEEK_END);
        /*文件存在,检查文件大小是否大于(8+sizeof(out_flag)*/             
        if (ftell(fp) < (8+sizeof(out_flag))) {
            log_i("1111111111111111111111111111111111111111111111111111111111111111");
            if (fwrite(&write_index, sizeof(write_index), 1, fp) != sizeof(write_index)) {
                LOG_E("write %s failed, line:%d", file_name, __LINE__);
            }
            fseek(fp, sizeof(read_index), SEEK_SET);
            if (fwrite(&read_index, sizeof(read_index), 1, fp) != sizeof(read_index)) {
                LOG_E("write %s failed, line:%d", file_name, __LINE__);
            }
            fseek(fp, sizeof(out_flag), SEEK_SET);
            if (fwrite(&read_index, sizeof(read_index), 1, fp) != sizeof(read_index)) {
                LOG_E("write %s failed, line:%d", file_name, __LINE__);
            }
            fseek(fp, 0, SEEK_SET);
            fclose(fp);
            return true;
        }
        fseek(fp, 0, SEEK_SET);
        /*检查3个初始指针的大小是否合规*/
        fread(&write_index, 1, sizeof(write_index), fp);
        log_w("write_index = %d",write_index);
        if (write_index > CUSTOM_FILE_STORAGE_MAX || write_index < 0) {
            fclose(fp);
            fp = fopen(file_name, "w+");
            fwrite(&write_index, sizeof(write_index), 1, fp);
        }
        fseek(fp, sizeof(read_index), SEEK_SET);
        fread(&read_index, 1, sizeof(read_index), fp);
        log_w("read_index = %d",read_index);
        if (read_index > CUSTOM_FILE_STORAGE_MAX || read_index < 0) {
            fclose(fp);
            fp = fopen(file_name, "w+");
            fwrite(&read_index, sizeof(read_index), 1, fp);
        }
        fseek(fp, sizeof(write_index) + sizeof(read_index), SEEK_SET);
        fread(&out_flag, 1, sizeof(out_flag), fp);
        log_w("out_flag = %d", out_flag);
        if (out_flag > read_index) {
            fclose(fp);
            fp = fopen(file_name, "w+");
            fwrite(&out_flag, sizeof(out_flag), 1, fp);
        }
    }
    if (fp) {
        fclose(fp);
    }
    return true;
}

bool customization_ocpp_file_storage_read(FILE *fp, charge_save_data_info *data, int *read_num) {

    int read_index = 0;
    memcpy(&read_index, read_num, sizeof(read_index));
    if (!fp) {
        LOG_E("open failed, line:%d", __LINE__);
        return false;
    }
    fseek(fp, read_index, SEEK_SET);
    if (fread(data, sizeof(charge_save_data_info), 1, fp) != 1) {
        LOG_E("read  failed, size:%d, line:%d", read_index, __LINE__);
        return false;
    }
    return true;
}

bool customization_ocpp_file_storage_write(FILE *fp, void *data, uint32_t size) {
    int wrire_index = 0, offset = 0;
    int out_flag = 0;
    if (!fp) {
        LOG_E("open failed, line:%d", __LINE__);
        return false;
    }

    fseek(fp, 0, SEEK_SET);
    fread(&wrire_index, sizeof(wrire_index), 1, fp);
    log_i("in write index : %d", wrire_index);
    offset = (2 * sizeof(wrire_index) + sizeof(out_flag)) + (wrire_index * size);
    log_i("offset : %d ", offset);
    fseek(fp, offset, SEEK_SET);
    if (fwrite(data, size, 1, fp) != 1) {
        LOG_E("write  failed, size:%d, line:%d", size, __LINE__);
        return false;
    }

    fseek(fp, 0, SEEK_SET);
    wrire_index++;
    if (wrire_index > CUSTOM_FILE_STORAGE_MAX - 1) {
        wrire_index = 0;
        /*溢出标志位 = 1,写入到file里面*/
        out_flag = 1;
        /*指针偏移到out_flag的位置*/
        fseek(fp, (0 + sizeof(wrire_index)) + (sizeof(out_flag)), SEEK_SET);
        if (fwrite(&out_flag, sizeof(out_flag), 1, fp) != 1) {
                LOG_E("write  failed, size:%d, line:%d", size, __LINE__);
            return false;
        }
        /*指针偏移回0*/
        fseek(fp, 0, SEEK_SET);                
    }
    if (fwrite(&wrire_index, sizeof(wrire_index), 1, fp) != 1) {
        LOG_E("write  failed, size:%d, line:%d", size, __LINE__);
        return false;
    }
    log_i("wirte succuss, wirte num = %d", wrire_index);
    return true;
}

bool customization_ocpp_file_reset(const char *__restrict file_name) {
    int write_index = 0;
    int read_index = 0;
    int out_flag = 0;
    bool ret = false;
    FILE *fp = fopen(file_name, "w");
    if (!fp) {
        LOG_E("RESET open failed, line:%d", __LINE__);
        goto _end;
    }
    fseek(fp, 0, SEEK_SET);
    if (ftell(fp) < 12) {
        fseek(fp, 0, SEEK_SET);
        if (fwrite(&write_index, sizeof(write_index), 1, fp) != sizeof(write_index)) {
            LOG_E("write %s failed, line:%d", file_name, __LINE__);
        }
        fseek(fp, 4, SEEK_SET);
        if (fwrite(&read_index, sizeof(read_index), 1, fp) != sizeof(read_index)) {
            LOG_E("write %s failed, line:%d", file_name, __LINE__);
        }
        fseek(fp, 8, SEEK_SET);
        if (fwrite(&out_flag, sizeof(out_flag), 1, fp) != sizeof(out_flag)) {
            LOG_E("write %s failed, line:%d", file_name, __LINE__);
        }
        ret = true;
        goto _end;
    }
    fseek(fp, 0, SEEK_SET);
    /*检查3个初始指针的大小是否合规*/
    fread(&write_index, 1, sizeof(write_index), fp);
    log_w("write_index = %d",write_index);
    if (write_index > CUSTOM_FILE_STORAGE_MAX || write_index < 0) {
        fclose(fp);
        fp = fopen(file_name, "w+");
        fwrite(&write_index, sizeof(write_index), 1, fp);
    }
    fseek(fp, sizeof(read_index), SEEK_SET);
    fread(&read_index, 1, sizeof(read_index), fp);
    log_w("read_index = %d", read_index);
    if (read_index > CUSTOM_FILE_STORAGE_MAX || read_index < 0) {
        fclose(fp);
        fp = fopen(file_name, "w+");
        fwrite(&read_index, sizeof(read_index), 1, fp);
    }
    fseek(fp, sizeof(write_index) + sizeof(read_index), SEEK_SET);
    fread(&out_flag, 1, sizeof(out_flag), fp);
    log_w("out_flag = %d", out_flag);
    if (out_flag > read_index) {
        fclose(fp);
        fp = fopen(file_name, "w+");
        fwrite(&out_flag, sizeof(out_flag), 1, fp);
    }

_end:
    if (fp) {
        fclose(fp);
    }
    return ret;
}